import tkinter as tk
from tkinter import ttk, filedialog, scrolledtext
import os
import sys
import re
from logic import AudioConverter

class AudioConverterUI:
    """音频转换工具的界面类"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("Ez MP3转换器")
        self.root.geometry("800x600")
        self.root.resizable(True, True)
        
        # 设置窗口图标
        self.set_window_icon()
        
        # 设置中文字体支持
        self.setup_fonts()
        
        # 创建转换器实例
        self.converter = AudioConverter()
        self.converter.set_callbacks(self.update_progress, self.add_log)
        
        # 转换状态
        self.converting = False
        
        # 创建界面元素
        self.create_widgets()
        
        # 布局界面
        self.layout_widgets()
        
        # 绑定事件
        self.bind_events()
    
    def set_window_icon(self):
        """设置窗口图标，适配开发环境和打包后环境"""
        try:
            # 优先尝试加载同目录下的0603.ico（开发环境）
            icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "0603.ico")
            
            # 如果是打包后的程序（PyInstaller会将资源放在sys._MEIPASS临时目录）
            if hasattr(sys, '_MEIPASS'):
                icon_path = os.path.join(sys._MEIPASS, "0603.ico")
            
            # 设置窗口图标
            self.root.iconbitmap(icon_path)
        except Exception as e:
            # 若图标加载失败，不影响程序运行
            self.add_log(f"图标加载失败：{str(e)}")
    
    def setup_fonts(self):
        """设置支持中文的字体"""
        default_font = ('SimHei', 10)
        self.root.option_add("*Font", default_font)
    
    def create_widgets(self):
        """创建所有界面组件"""
        # 输入部分
        self.input_frame = ttk.LabelFrame(self.root, text="输入文件/目录")
        
        self.input_path_var = tk.StringVar()
        self.input_entry = ttk.Entry(self.input_frame, textvariable=self.input_path_var, width=50)
        
        self.select_file_btn = ttk.Button(self.input_frame, text="选择文件", command=self.select_file)
        self.select_dir_btn = ttk.Button(self.input_frame, text="选择目录", command=self.select_directory)
        
        # 输出部分
        self.output_frame = ttk.LabelFrame(self.root, text="输出设置")
        
        self.output_dir_var = tk.StringVar()
        self.output_entry = ttk.Entry(self.output_frame, textvariable=self.output_dir_var, width=50)
        
        self.select_output_btn = ttk.Button(self.output_frame, text="选择输出目录", command=self.select_output_directory)
        self.use_input_dir_var = tk.BooleanVar(value=True)
        self.use_input_dir_check = ttk.Checkbutton(
            self.output_frame, 
            text="使用输入文件所在目录", 
            variable=self.use_input_dir_var,
            command=self.toggle_output_dir
        )
        
        # 格式和质量设置
        self.settings_frame = ttk.LabelFrame(self.root, text="转换设置")
        
        self.format_label = ttk.Label(self.settings_frame, text="输出格式:")
        self.format_var = tk.StringVar(value="mp3")
        self.format_combobox = ttk.Combobox(
            self.settings_frame, 
            textvariable=self.format_var,
            values=["mp3", "m4a"],
            state="readonly",
            width=10
        )
        
        self.quality_label = ttk.Label(self.settings_frame, text="质量:")
        # 默认质量设置为"源文件质量"
        self.quality_var = tk.StringVar(value="源文件质量")
        self.quality_combobox = ttk.Combobox(
            self.settings_frame, 
            textvariable=self.quality_var,
            values=["高质量", "中等质量", "低质量", "源文件质量", "自定义"],
            width=12
        )
        
        # 自定义质量输入框（只输入数字）
        self.custom_quality_var = tk.StringVar(value="192")
        self.custom_quality_entry = ttk.Entry(
            self.settings_frame, 
            textvariable=self.custom_quality_var,
            width=8,
            state=tk.DISABLED  # 默认禁用
        )
        
        # 添加"覆盖已存在文件"复选框
        self.overwrite_var = tk.BooleanVar(value=False)  # 默认不勾选
        self.overwrite_check = ttk.Checkbutton(
            self.settings_frame,
            text="覆盖已存在文件",
            variable=self.overwrite_var
        )
        
        # 转换按钮 - 增加宽度
        self.convert_btn = ttk.Button(self.root, text="开始转换", command=self.start_conversion, width=15)
        
        # 进度条
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(self.root, variable=self.progress_var, maximum=100)
        
        # 日志区域
        self.log_frame = ttk.LabelFrame(self.root, text="转换日志")
        self.log_text = scrolledtext.ScrolledText(self.log_frame, wrap=tk.WORD, height=10)
        self.log_text.config(state=tk.DISABLED)
        
        # 状态标签
        self.status_var = tk.StringVar(value="就绪")
        self.status_label = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
    
    def layout_widgets(self):
        """布局所有界面组件"""
        # 输入部分布局
        self.input_frame.pack(fill=tk.X, padx=10, pady=5, ipady=5)
        self.input_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        self.select_file_btn.pack(side=tk.LEFT, padx=2)
        self.select_dir_btn.pack(side=tk.LEFT, padx=2)
        
        # 输出部分布局
        self.output_frame.pack(fill=tk.X, padx=10, pady=5, ipady=5)
        self.output_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        self.select_output_btn.pack(side=tk.LEFT, padx=2)
        self.use_input_dir_check.pack(side=tk.LEFT, padx=5)
        
        # 设置部分布局
        self.settings_frame.pack(fill=tk.X, padx=10, pady=5, ipady=5)
        self.format_label.pack(side=tk.LEFT, padx=5)
        self.format_combobox.pack(side=tk.LEFT, padx=5)
        self.quality_label.pack(side=tk.LEFT, padx=5)
        self.quality_combobox.pack(side=tk.LEFT, padx=5)
        self.custom_quality_entry.pack(side=tk.LEFT, padx=5)
        # 放置"覆盖已存在文件"复选框
        self.overwrite_check.pack(side=tk.LEFT, padx=15)
        
        # 转换按钮
        self.convert_btn.pack(pady=10)
        
        # 进度条
        self.progress_bar.pack(fill=tk.X, padx=10, pady=5)
        
        # 日志区域
        self.log_frame.pack(fill=tk.BOTH, padx=10, pady=5, expand=True)
        self.log_text.pack(fill=tk.BOTH, padx=5, pady=5, expand=True)
        
        # 状态标签
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 初始禁用输出目录
        self.toggle_output_dir()
        # 初始检查质量选择状态
        self.on_quality_change()
    
    def bind_events(self):
        """绑定事件处理函数"""
        # 质量选择变化事件
        self.quality_combobox.bind("<<ComboboxSelected>>", lambda e: self.on_quality_change())
        # 输入路径变化时处理引号
        self.input_path_var.trace_add("write", self.process_path_quotes)
        # 自定义质量输入框限制只能输入数字
        self.custom_quality_entry.config(validate="key", validatecommand=(self.root.register(self.validate_number_input), "%P"))
    
    def validate_number_input(self, value):
        """验证输入是否为数字"""
        if not value:  # 允许空值，后续会有进一步验证
            return True
        return value.isdigit()
    
    def process_path_quotes(self, *args):
        """处理路径中的引号"""
        path = self.input_path_var.get()
        # 去除首尾的引号
        cleaned_path = path.strip('"\'')
        if cleaned_path != path:
            self.input_path_var.set(cleaned_path)
    
    def on_quality_change(self):
        """处理质量选择变化"""
        quality = self.quality_var.get()
        if quality == "自定义":
            self.custom_quality_entry.config(state=tk.NORMAL)
        else:
            self.custom_quality_entry.config(state=tk.DISABLED)
    
    def toggle_output_dir(self):
        """根据复选框状态启用/禁用输出目录选择"""
        if self.use_input_dir_var.get():
            self.output_entry.config(state=tk.DISABLED)
            self.select_output_btn.config(state=tk.DISABLED)
        else:
            self.output_entry.config(state=tk.NORMAL)
            self.select_output_btn.config(state=tk.NORMAL)
    
    def select_file(self):
        """选择单个个输入文件"""
        file_path = filedialog.askopenfilename(
            title="选择音频/视频文件",
            filetypes=[("支持的文件", self.converter.get_supported_input_formats_str()), ("所有文件", "*.*")]
        )
        if file_path:
            self.input_path_var.set(file_path)
            if self.use_input_dir_var.get():
                self.output_dir_var.set(os.path.dirname(file_path))
    
    def select_directory(self):
        """选择输入目录"""
        dir_path = filedialog.askdirectory(title="选择目录")
        if dir_path:
            self.input_path_var.set(dir_path)
            if self.use_input_dir_var.get():
                self.output_dir_var.set(dir_path)
    
    def select_output_directory(self):
        """选择输出目录"""
        dir_path = filedialog.askdirectory(title="选择输出目录")
        if dir_path:
            self.output_dir_var.set(dir_path)
    
    def add_log(self, message):
        """向日志区域添加消息"""
        self.log_text.config(state=tk.NORMAL)
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)  # 滚动到最后一行
        self.log_text.config(state=tk.DISABLED)
        self.root.update_idletasks()  # 更新界面
    
    def update_progress(self, value):
        """更新进度条"""
        self.progress_var.set(value)
        self.status_var.set(f"正在转换... {value}%")
        self.root.update_idletasks()  # 更新界面
    
    def validate_custom_quality(self, quality_str):
        """验证自定义质量输入是否有效（仅数字）"""
        if not quality_str:
            return False, "请输入自定义质量值"
        
        # 检查是否为数字
        if not quality_str.isdigit():
            return False, "请仅输入数字"
        
        # 检查数值是否在合理范围内
        try:
            bitrate = int(quality_str)
            if bitrate < 32 or bitrate > 320:
                return False, "比特率应在32到320之间"
        except ValueError:
            return False, "请输入有效的数字"
            
        return True, quality_str
    
    def start_conversion(self):
        """开始转换过程"""
        if self.converting:
            return
            
        # 验证输入
        input_path = self.input_path_var.get()
        # 处理可能的引号
        input_path = input_path.strip('"\'')
        
        if not input_path or not os.path.exists(input_path):
            self.add_log("请选择有效的输入文件或目录")
            return
        
        # 获取输出目录
        output_dir = None
        if not self.use_input_dir_var.get():
            output_dir = self.output_dir_var.get()
            if not output_dir:
                self.add_log("请选择输出目录")
                return
        
        # 获取格式和质量设置
        output_format = self.format_var.get()
        quality = self.quality_var.get()
        custom_quality = None
        
        # 验证自定义质量（如果选择了自定义）
        if quality == "自定义":
            valid, msg = self.validate_custom_quality(self.custom_quality_var.get())
            if not valid:
                self.add_log(msg)
                return
            custom_quality = msg
        
        # 获取覆盖文件选项状态
        overwrite = self.overwrite_var.get()
        
        # 准备转换
        self.converting = True
        self.convert_btn.config(text="转换中...", state=tk.DISABLED)
        self.progress_var.set(0)
        self.add_log(f"准备转换为 {output_format} 格式，质量: {quality}{' (' + custom_quality + 'k)' if custom_quality else ''}")
        if overwrite:
            self.add_log("注意：已启用覆盖模式，将替换已存在的文件")
        
        # 在后台线程中执行转换，避免界面冻结
        import threading
        conversion_thread = threading.Thread(
            target=self.perform_conversion,
            args=(input_path, output_format, quality, output_dir, custom_quality, overwrite)
        )
        conversion_thread.daemon = True
        conversion_thread.start()
    
    def perform_conversion(self, input_path, output_format, quality, output_dir, custom_quality, overwrite):
        """执行转换（在后台线程中运行）"""
        try:
            # 调用转换逻辑
            success, total = self.converter.batch_convert(
                input_path, output_format, quality, output_dir, custom_quality, overwrite
            )
            
            # 更新状态
            if total > 0:
                self.status_var.set(f"转换完成: 成功 {success}/{total}")
            else:
                self.status_var.set("就绪")
        except Exception as e:
            self.add_log(f"转换过程出错: {str(e)}")
            self.status_var.set("转换出错")
        finally:
            # 恢复界面状态
            self.converting = False
            self.root.after(0, lambda: self.convert_btn.config(text="开始转换", state=tk.NORMAL))

if __name__ == "__main__":
    root = tk.Tk()

    # 设置应用程序图标（在打包环境和开发环境都有效）
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.dirname(os.path.abspath(__file__))
    icon_path = os.path.join(base_path, '0603.ico')
    if os.path.exists(icon_path):
        root.iconbitmap(icon_path)

    # 主题：cyborg,journal,darkly,flatly,solar,minty,litera,united,pulse,cosmo,lumen
    import ttkbootstrap
    style = ttkbootstrap.Style(theme='cosmo')
    app = AudioConverterUI(root)
    root.mainloop()
